import java.util.ArrayList;
/**
 *  An object of type DynamicLongArray acts like a dynamic array of long.
 *  internally an ArrayList holds the data for the array
 */
public class DynamicLongArray 
{

   private ArrayList<Long> data;  // An array to hold the data.
   // the index that is the next empty space in the array

   /**
    * Constructor creates an array with an initial size of 1.
    * 
    */   
   public DynamicLongArray() 
   {
      data = new ArrayList<Long>();
   }
   
   /**
    * Gets the array that holds the data
    * 
    * @return the entire Array used by the instance 
    */
   public Long[] getArray()
   {
	   Long[] temp= new Long[data.size()];
	   return data.toArray(temp);
   }

   
   /**
    *  Makes the array a new array of length 1.
    */
   public void deleteArray()
   {
   		data.clear();
   }
   
   /**
    * Returns the size of the array
    * 
    * @return the size of the array
    */
   public int getSize()
   {
	   return data.size();
   }
   
   /**
    * Averages the values in the array if the array has no elements
    * the method returns 0.
    * 
    * @return the average value of the array or zero if empty
    */
   public long average()
   {
	   long sum= 0;
	   // returns zero if no elements in array
	   if(data.size()==0) return 0;
	   for(int k=0; k<data.size(); k++)
	   {
		   sum= sum+data.get(k);
	   }
	   return sum/(long)data.size();
   }
   
   /**
    * Finds the lowest value in the Array
    * 
    * @return the lowest value will return 0 if empty
    */
   public long getMin()
   {
	   // arbitrary assignment to one of the values int the ArrayList
	   if(data.size()==0) return 0;
	   long currentMin= data.get(0).longValue();
	   for(Long k : data)
	   {
		   if(k.longValue()<currentMin) currentMin= k.longValue();
	   }
	   return currentMin;
   }
   
   /**
    *  Get the value from the specified position in the array.
    *  Returns zero if outside the range of the array.
    *  
    *  @param position the index
    */
   public long get(int position) 
   {
      if(position >= data.size()) return 0;
      else return data.get(position);
   }
   
   /**
    * Stores a value in the array.
    * 
    * @param position the index
    * @param value the value to store
    */
   public void set(int position, long value) 
   {
	  while(data.size()<position+1) data.add(new Long(0L));
      data.set(position, value);
   }
   /**
    * Stores a value to the first unused index in the array.
    * 
    * @param value the value to store
    */
   public void add(long value)
   {
	   data.add(value);
   }
   
   /**
    * Adds another DyanmicLongArray on the end of this one.
    * 
    * @param addition the array to combine with
    */
   public void add(DynamicLongArray addition)
   {
	   data.addAll(addition.data);
   }
   
   /**
    * Adds a array of long on the end of this one.
    * 
    * @param addition the array to combine with
    */
   public void add(long[] addition)
   {
	   for(int k=0; k<addition.length; k++)
	   {
		  add(addition[k]); 
	   }
   }
   
   /**
    * Adds a array of int on the end of this one.
    * 
    * @param addition the array to combine with
    */
   public void add(int[] addition)
   {
	   for(int k=0; k<addition.length; k++)
	   {
		  add(addition[k]); 
	   }
   }
   
   /**
    * Adds each value in a DynamicLongArray to its corresponding value  
    * @param addition the array to merge into this
    */
   public void merge(DynamicLongArray addition)
   {
	   for(int k=0; k<addition.getArray().length; k++)
	   {
		   set(k, get(k)+addition.getArray()[k]);
	   }
   }
   
   /**
    * Adds each value in a array of int to its corresponding value  
    * @param addition the array to merge into this
    */
   public void merge(int[] addition)
   {
	   for(int k=0; k<addition.length; k++)
	   {
		   set(k, get(k)+addition[k]);
	   }
   }
  
   /**
    * Creates a string representation of the DynamicLongArray
    */
   @Override
   public String toString()
   {
	   String temp= "";
	   for(int k=0; k<data.size(); k++)
	   {
		   temp+= data.get(k)+"c";
	   }
	   temp+="e";
	   return temp;
   }
   
   /**
    * Reverse of toString creates a DynamicLongArray from a String.
    * will throw an IllegalArgumentException if it can't parse the String.
    * 
    * @param source the string representing a DynamicLongArray.
    * 
    * @return the DynamicLongArray
    */
   public static DynamicLongArray fromString(String source)
   {
	   char[] chars= source.toCharArray();
	   String next= "";
	   DynamicLongArray temp= new DynamicLongArray();
	   for(int k=0; k<chars.length; k++)
	   {
		   if(Character.isDigit(chars[k]))
		   {
			   next+= chars[k];
		   }
		   else if(chars[k]=='c')
		   {
			   long nextIndex= Long.parseLong(next);
			   temp.add(nextIndex);
			   next= "";
		   }
		   else if(chars[k]=='e')
		   {
			   break;
		   }
		   else throw new IllegalArgumentException("Invaild Data");
	   }
	   return temp;
   }

} 
